#!/usr/bin/env python3
import asyncio
import time
from connection import Connection
from logger import Logger
from config import Config


class ConnectionManager:
    def __init__(self, client_id: str, user_id: str):
        self.connections = {}
        self.config = Config()
        self.logger = Logger(user_id, self.config.get_log_dir())
        self.client_id = client_id
        self.user_id = user_id
        self.lock = asyncio.Lock()
        self.alive_time = time.time()  # 记录最后活跃时间
    
    def update_alive_time(self):
        """更新最后活跃时间"""
        self.alive_time = time.time()
        
    def is_expired(self, max_idle_time=24*3600):  # 默认24小时
        """检查是否已过期
        参数:
        - max_idle_time: 最大空闲时间（秒），默认24小时
        """
        return time.time() - self.alive_time > max_idle_time

    async def create_connection(self, name, ip, port):
        self.update_alive_time()
        async with self.lock:
            if name in self.connections:
                # 检查是否是重复创建（name/ip/port都相同）
                existing_conn = self.connections[name]
                if existing_conn.ip == ip and existing_conn.port == port:
                    # 重复创建，返回成功
                    return existing_conn
                else:
                    # name已使用，但ip和port不同
                    return {'error': f'连接名称 {name} 已被使用'}

            # 创建新连接
            conn = Connection(name, ip, port, self.logger, self.user_id)
            if not await conn.connect():
                return {'error': f'无法连接到 {ip}:{port}'}

            self.connections[name] = conn
            return conn

    async def get_connections(self):
        self.update_alive_time()
        async with self.lock:
            return list(self.connections.values())

    async def list_connections(self):
        self.update_alive_time()
        """列出所有连接"""
        connections = await self.get_connections()
        # 使用get_info()方法获取可序列化的连接信息
        return [conn.get_info() for conn in connections]

    async def get_connection(self, name):
        self.update_alive_time()
        async with self.lock:
            if name not in self.connections:
                return {'error': f'找不到连接: {name}'}
            return self.connections[name]

    async def send_command(self, name, cmd):
        self.update_alive_time()
        conn = await self.get_connection(name)
        if isinstance(conn, dict) and 'error' in conn:
            return conn
        return await conn.send_command(cmd)

    async def broadcast_command(self, cmd):
        self.update_alive_time()
        results = {}
        async with self.lock:
            connections_copy = list(self.connections.items())

        tasks = []
        for name, conn in connections_copy:
            if conn.is_alive():
                task = asyncio.create_task(self._send_command_to_connection(name, conn, cmd))
                tasks.append(task)
            else:
                results[name] = {'error': '连接已关闭'}

        if tasks:
            task_results = await asyncio.gather(*tasks, return_exceptions=True)
            for i, (name, _) in enumerate([t for t in connections_copy if t[1].is_alive()]):
                if isinstance(task_results[i], Exception):
                    results[name] = {'error': f'发送命令失败: {str(task_results[i])}'}
                elif isinstance(task_results[i], dict) and 'error' in task_results[i]:
                    results[name] = task_results[i]
                else:
                    results[name] = {'result': task_results[i]}

        return results

    async def _send_command_to_connection(self, name, conn, cmd):
        try:
            return await conn.send_command(cmd)
        except Exception as e:
            return {'error': f'发送命令失败: {str(e)}'}

    async def close_connection(self, name):
        self.update_alive_time()
        # 先获取锁检查连接是否存在
        async with self.lock:
            if name not in self.connections:
                return {'error': f'找不到连接: {name}'}
            conn = self.connections[name]
        
        # 释放锁后关闭连接
        if await conn.close():
            # 再次获取锁删除连接
            async with self.lock:
                # 双重检查，防止并发删除
                if name in self.connections:
                    del self.connections[name]
            return {'success': True}
        return {'success': False}

    async def close_all_connections(self):
        self.update_alive_time()
        # 获取当前连接名称列表
        async with self.lock:
            names = list(self.connections.keys())
        
        # 并行关闭所有连接
        if not names:
            return 0
        
        tasks = []
        for name in names:
            tasks.append(self.close_connection(name))
        
        # 等待所有任务完成
        results = await asyncio.gather(*tasks)
        
        # 统计成功关闭的连接数
        count = 0
        for result in results:
            if isinstance(result, dict) and result.get('success'):
                count += 1
        return count